import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA

# 配置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Heiti TC', 'STHeiti']
plt.rcParams['axes.unicode_minus'] = False

# 加载数据集
iris = load_iris()
X, y = iris.data, iris.target
feature_names = iris.feature_names
target_names = iris.target_names

# 创建画布（2行2列布局）
plt.figure(figsize=(18, 12))

# 定义要测试的n_components值
n_components_list = [1, 2, 3]

# 遍历不同n_components值
for idx, n in enumerate(n_components_list):
    # PCA降维
    pca = PCA(n_components=n)
    X_pca = pca.fit_transform(X)

    # 计算累计方差解释率
    explained_variance = pca.explained_variance_ratio_
    cumulative_variance = np.cumsum(explained_variance)

    # 绘制子图
    plt.subplot(2, 2, idx + 1)

    if n == 1:
        # 一维数据用直方图展示分布
        plt.hist(X_pca, bins=15, edgecolor='k', alpha=0.7)
        plt.title(f'PCA 1D降维 (保留方差: {cumulative_variance[0]:.3%})')
        plt.xlabel('第一主成分')
        plt.ylabel('样本密度')
    else:
        # 二维及以上用散点图
        plt.scatter(X_pca[:, 0], X_pca[:, 1] if n >= 2 else 0,
                    c=y, edgecolor='k', s=50)
        plt.title(f'PCA {n}D降维 (保留方差: {cumulative_variance[-1]:.3%})')
        plt.xlabel(f'主成分1 ({explained_variance[0] * 100:.3f}%)')
        if n >= 2:
            plt.ylabel(f'主成分2 ({explained_variance[1] * 100:.3f}%)')
        else:
            plt.ylabel('固定值')

    # 添加类别标签
    legend_elements = [plt.Line2D([0], [0], marker='o', color='w',
                                  label=target_names[i],
                                  markerfacecolor=plt.cm.Set1(i), markersize=10)
                       for i in range(3)]
    plt.legend(handles=legend_elements, loc='upper right')

# 添加全局说明
plt.suptitle('不同n_components值的PCA降维对比', y=1.02, fontsize=16)
plt.tight_layout()
plt.show()